package com.eduagent.xwqeduagent.utils.oj;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import java.io.IOException;
import java.util.List;
import java.util.Map;

/**
 * Judge0 API客户端
 * 负责与Judge0 API进行通信
 */
@Component
public class JudgeClient {
    private static final Logger logger = LoggerFactory.getLogger(JudgeClient.class);

    private final RestTemplate restTemplate;

    @Value("${judge0.api.url}")
    private String apiUrl;

    @Value("${judge0.api.auth-token}")
    private String authToken;

    @Value("${judge0.api.auth-header}")
    private String authHeader;

    @Value("${judge0.api.host-header:x-rapidapi-host}")
    private String hostHeader;

    @Value("${judge0.api.host-value:}")
    private String hostValue;

    @Value("${judge0.api.base64-encoded:false}")
    private boolean base64Encoded;

    public JudgeClient() {
        this.restTemplate = new RestTemplate();
    }

    /**
     * 创建HTTP请求头
     * @return HttpHeaders对象
     */
    private HttpHeaders createHeaders() {
        HttpHeaders headers = new HttpHeaders();
        headers.set(authHeader, authToken);
        if (hostValue != null && !hostValue.isEmpty()) {
            headers.set(hostHeader, hostValue);
        }
        headers.setContentType(MediaType.APPLICATION_JSON);
        return headers;
    }

    /**
     * 校验认证信息
     * @return 认证是否有效
     * @throws IOException 网络错误
     */
    public boolean authenticate() throws IOException {
        try {
            String url = apiUrl + "/authenticate";
            HttpEntity<Void> entity = new HttpEntity<>(createHeaders());
            ResponseEntity<Void> response = restTemplate.exchange(url, HttpMethod.HEAD, entity, Void.class);
            return response.getStatusCode() == HttpStatus.OK;
        } catch (Exception e) {
            logger.error("认证失败", e);
            throw new IOException("认证失败: " + e.getMessage());
        }
    }

    /**
     * 校验授权信息
     * @return 授权是否有效
     * @throws IOException 网络错误
     */
    public boolean authorize() throws IOException {
        try {
            String url = apiUrl + "/authorize";
            HttpEntity<Void> entity = new HttpEntity<>(createHeaders());
            ResponseEntity<Void> response = restTemplate.exchange(url, HttpMethod.HEAD, entity, Void.class);
            return response.getStatusCode() == HttpStatus.OK;
        } catch (Exception e) {
            logger.error("授权失败", e);
            throw new IOException("授权失败: " + e.getMessage());
        }
    }

    /**
     * 提交代码评测
     * @param submission 提交信息
     * @param wait 是否等待结果
     * @param base64 是否Base64编码
     * @return 评测结果
     * @throws IOException 网络错误
     */
    public JudgeSubmissionResponse createSubmission(JudgeSubmission submission, boolean wait, boolean base64) throws IOException {
        try {
            String url = UriComponentsBuilder.fromHttpUrl(apiUrl + "/submissions")
                    .queryParam("base64_encoded", base64 || base64Encoded)
                    .queryParam("wait", wait)
                    .build()
                    .toUriString();

            HttpEntity<JudgeSubmission> entity = new HttpEntity<>(submission, createHeaders());
            ResponseEntity<JudgeSubmissionResponse> response = restTemplate.exchange(
                    url,
                    HttpMethod.POST,
                    entity,
                    JudgeSubmissionResponse.class
            );
            return response.getBody();
        } catch (Exception e) {
            logger.error("提交代码评测失败", e);
            throw new IOException("提交代码评测失败: " + e.getMessage());
        }
    }

    /**
     * 批量提交代码评测
     * @param submissions 多个提交信息
     * @param wait 是否等待结果
     * @param base64 是否Base64编码
     * @return 评测结果列表
     * @throws IOException 网络错误
     */
    public List<JudgeSubmissionResponse> createBatchSubmissions(List<JudgeSubmission> submissions, boolean wait, boolean base64) throws IOException {
        try {
            String url = UriComponentsBuilder.fromHttpUrl(apiUrl + "/submissions/batch")
                    .queryParam("base64_encoded", base64 || base64Encoded)
                    .queryParam("wait", wait)
                    .build()
                    .toUriString();

            HttpEntity<List<JudgeSubmission>> entity = new HttpEntity<>(submissions, createHeaders());
            ResponseEntity<List<JudgeSubmissionResponse>> response = restTemplate.exchange(
                    url,
                    HttpMethod.POST,
                    entity,
                    new ParameterizedTypeReference<List<JudgeSubmissionResponse>>() {}
            );
            return response.getBody();
        } catch (Exception e) {
            logger.error("批量提交代码评测失败", e);
            throw new IOException("批量提交代码评测失败: " + e.getMessage());
        }
    }

    /**
     * 获取评测结果
     * @param token 提交令牌
     * @param base64 是否Base64编码
     * @param fields 需要返回的字段
     * @return 评测结果
     * @throws IOException 网络错误
     */
    public JudgeSubmissionResponse getSubmission(String token, boolean base64, String fields) throws IOException {
        try {
            UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(apiUrl + "/submissions/" + token)
                    .queryParam("base64_encoded", base64 || base64Encoded);
            
            if (fields != null && !fields.isEmpty()) {
                builder.queryParam("fields", fields);
            }
            
            String url = builder.build().toUriString();

            HttpEntity<Void> entity = new HttpEntity<>(createHeaders());
            ResponseEntity<JudgeSubmissionResponse> response = restTemplate.exchange(
                    url,
                    HttpMethod.GET,
                    entity,
                    JudgeSubmissionResponse.class
            );
            return response.getBody();
        } catch (Exception e) {
            logger.error("获取评测结果失败", e);
            throw new IOException("获取评测结果失败: " + e.getMessage());
        }
    }

    /**
     * 获取批量评测结果
     * @param tokens 提交令牌列表（逗号分隔的字符串）
     * @param base64 是否Base64编码
     * @param fields 需要返回的字段
     * @return 评测结果列表
     * @throws IOException 网络错误
     */
    public List<JudgeSubmissionResponse> getBatchSubmissions(String tokens, boolean base64, String fields) throws IOException {
        try {
            UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(apiUrl + "/submissions/batch")
                    .queryParam("tokens", tokens)
                    .queryParam("base64_encoded", base64 || base64Encoded);
            
            if (fields != null && !fields.isEmpty()) {
                builder.queryParam("fields", fields);
            }
            
            String url = builder.build().toUriString();

            HttpEntity<Void> entity = new HttpEntity<>(createHeaders());
            ResponseEntity<List<JudgeSubmissionResponse>> response = restTemplate.exchange(
                    url,
                    HttpMethod.GET,
                    entity,
                    new ParameterizedTypeReference<List<JudgeSubmissionResponse>>() {}
            );
            return response.getBody();
        } catch (Exception e) {
            logger.error("获取批量评测结果失败", e);
            throw new IOException("获取批量评测结果失败: " + e.getMessage());
        }
    }

    /**
     * 删除评测提交
     * @param token 提交令牌
     * @return 操作结果
     * @throws IOException 网络错误
     */
    public JudgeSubmissionResponse deleteSubmission(String token) throws IOException {
        try {
            String url = apiUrl + "/submissions/" + token;
            HttpEntity<Void> entity = new HttpEntity<>(createHeaders());
            ResponseEntity<JudgeSubmissionResponse> response = restTemplate.exchange(
                    url,
                    HttpMethod.DELETE,
                    entity,
                    JudgeSubmissionResponse.class
            );
            return response.getBody();
        } catch (Exception e) {
            logger.error("删除评测提交失败", e);
            throw new IOException("删除评测提交失败: " + e.getMessage());
        }
    }

    /**
     * 获取支持的编程语言列表
     * @param all 是否包含所有语言（包括归档的语言）
     * @return 语言列表
     * @throws IOException 网络错误
     */
    public Object getLanguages(boolean all) throws IOException {
        try {
            String url = UriComponentsBuilder.fromHttpUrl(apiUrl + "/languages")
                    .queryParam("all", all)
                    .build()
                    .toUriString();
            
            HttpEntity<Void> entity = new HttpEntity<>(createHeaders());
            ResponseEntity<Object> response = restTemplate.exchange(
                    url,
                    HttpMethod.GET,
                    entity,
                    Object.class
            );
            return response.getBody();
        } catch (Exception e) {
            logger.error("获取语言列表失败", e);
            throw new IOException("获取语言列表失败: " + e.getMessage());
        }
    }

    /**
     * 获取特定语言的信息
     * @param languageId 语言ID
     * @return 语言信息
     * @throws IOException 网络错误
     */
    public Object getLanguage(int languageId) throws IOException {
        try {
            String url = apiUrl + "/languages/" + languageId;
            HttpEntity<Void> entity = new HttpEntity<>(createHeaders());
            ResponseEntity<Object> response = restTemplate.exchange(
                    url,
                    HttpMethod.GET,
                    entity,
                    Object.class
            );
            return response.getBody();
        } catch (Exception e) {
            logger.error("获取语言信息失败", e);
            throw new IOException("获取语言信息失败: " + e.getMessage());
        }
    }

    /**
     * 获取所有状态列表
     * @return 状态列表
     * @throws IOException 网络错误
     */
    public Object getStatuses() throws IOException {
        try {
            String url = apiUrl + "/statuses";
            HttpEntity<Void> entity = new HttpEntity<>(createHeaders());
            ResponseEntity<Object> response = restTemplate.exchange(
                    url,
                    HttpMethod.GET,
                    entity,
                    Object.class
            );
            return response.getBody();
        } catch (Exception e) {
            logger.error("获取状态列表失败", e);
            throw new IOException("获取状态列表失败: " + e.getMessage());
        }
    }

    /**
     * 获取系统信息
     * @return 系统信息
     * @throws IOException 网络错误
     */
    public Object getSystemInfo() throws IOException {
        try {
            String url = apiUrl + "/system_info";
            HttpEntity<Void> entity = new HttpEntity<>(createHeaders());
            ResponseEntity<Map> response = restTemplate.exchange(
                    url,
                    HttpMethod.GET,
                    entity,
                    Map.class
            );
            return response.getBody();
        } catch (Exception e) {
            logger.error("获取系统信息失败", e);
            throw new IOException("获取系统信息失败: " + e.getMessage());
        }
    }

    /**
     * 获取配置信息
     * @return 配置信息
     * @throws IOException 网络错误
     */
    public Object getConfigInfo() throws IOException {
        try {
            String url = apiUrl + "/config_info";
            HttpEntity<Void> entity = new HttpEntity<>(createHeaders());
            ResponseEntity<Map> response = restTemplate.exchange(
                    url,
                    HttpMethod.GET,
                    entity,
                    Map.class
            );
            return response.getBody();
        } catch (Exception e) {
            logger.error("获取配置信息失败", e);
            throw new IOException("获取配置信息失败: " + e.getMessage());
        }
    }

    /**
     * 获取统计信息
     * @param invalidateCache 是否刷新缓存
     * @return 统计信息
     * @throws IOException 网络错误
     */
    public Object getStatistics(boolean invalidateCache) throws IOException {
        try {
            String url = UriComponentsBuilder.fromHttpUrl(apiUrl + "/statistics")
                    .queryParam("invalidate_cache", invalidateCache)
                    .build()
                    .toUriString();
            
            HttpEntity<Void> entity = new HttpEntity<>(createHeaders());
            ResponseEntity<Object> response = restTemplate.exchange(
                    url,
                    HttpMethod.GET,
                    entity,
                    Object.class
            );
            return response.getBody();
        } catch (Exception e) {
            logger.error("获取统计信息失败", e);
            throw new IOException("获取统计信息失败: " + e.getMessage());
        }
    }

    /**
     * 获取工作进程信息
     * @return 工作进程信息
     * @throws IOException 网络错误
     */
    public Object getWorkers() throws IOException {
        try {
            String url = apiUrl + "/workers";
            HttpEntity<Void> entity = new HttpEntity<>(createHeaders());
            ResponseEntity<Object> response = restTemplate.exchange(
                    url,
                    HttpMethod.GET,
                    entity,
                    Object.class
            );
            return response.getBody();
        } catch (Exception e) {
            logger.error("获取工作进程信息失败", e);
            throw new IOException("获取工作进程信息失败: " + e.getMessage());
        }
    }

    /**
     * 获取关于信息
     * @return 关于信息
     * @throws IOException 网络错误
     */
    public Object getAbout() throws IOException {
        try {
            String url = apiUrl + "/about";
            HttpEntity<Void> entity = new HttpEntity<>(createHeaders());
            ResponseEntity<Object> response = restTemplate.exchange(
                    url,
                    HttpMethod.GET,
                    entity,
                    Object.class
            );
            return response.getBody();
        } catch (Exception e) {
            logger.error("获取关于信息失败", e);
            throw new IOException("获取关于信息失败: " + e.getMessage());
        }
    }

    /**
     * 获取版本信息
     * @return 版本信息
     * @throws IOException 网络错误
     */
    public Object getVersion() throws IOException {
        try {
            String url = apiUrl + "/version";
            HttpEntity<Void> entity = new HttpEntity<>(createHeaders());
            ResponseEntity<Object> response = restTemplate.exchange(
                    url,
                    HttpMethod.GET,
                    entity,
                    Object.class
            );
            return response.getBody();
        } catch (Exception e) {
            logger.error("获取版本信息失败", e);
            throw new IOException("获取版本信息失败: " + e.getMessage());
        }
    }

    /**
     * 获取许可证信息
     * @return 许可证信息
     * @throws IOException 网络错误
     */
    public Object getLicense() throws IOException {
        try {
            String url = apiUrl + "/license";
            HttpEntity<Void> entity = new HttpEntity<>(createHeaders());
            ResponseEntity<Object> response = restTemplate.exchange(
                    url,
                    HttpMethod.GET,
                    entity,
                    Object.class
            );
            return response.getBody();
        } catch (Exception e) {
            logger.error("获取许可证信息失败", e);
            throw new IOException("获取许可证信息失败: " + e.getMessage());
        }
    }
} 